/**
 * 
 */
package edu.arizona.bio5.onto.modularity;

import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.semanticweb.owlapi.model.OWLEntity;

/**
 * Represents the signature as a collection of URIs
 * 
 * @author Pavel Klinov
 *
 */
public class Signature implements Iterable<URI> {

	private final Set<URI> mSig;
	
	public Signature() {
		mSig = new HashSet<URI>();
	}
	
	public Signature(final Signature sig) {
		mSig = new HashSet<URI>(sig.getURIs());
	}
	
	public Signature(URI... sig) {
		mSig = new HashSet<URI>(Arrays.asList(sig));
	}
	
	public Signature(Collection<OWLEntity> sig) {
		mSig = new HashSet<URI>(sig.size()); 
		
		for (OWLEntity term : sig) mSig.add(term.getIRI().toURI());
	}

	@Override
	public boolean equals(Object arg) {

		if (arg == null || !(arg instanceof Signature)) {
			return false;
		}
		else {
			return mSig.equals(((Signature)arg).getURIs());
		}
	}

	public Set<URI> getURIs() {
		return mSig;
	}

	public void addURI(URI termURI) {
		mSig.add(termURI);
	}
	
	public void add(Signature sig) {
		mSig.addAll(sig.getURIs());
	}
	
	public void addOWLEntity(OWLEntity term) {
		mSig.add(term.getIRI().toURI());
	}
	
	public void addOWLEntities(Collection<OWLEntity> terms) {
		for (OWLEntity term : terms) addOWLEntity(term);
	}
	
	public void removeURI(URI termURI) {
		mSig.remove(termURI);
	}
	
	public void remove(Signature sig) {
		mSig.removeAll(sig.getURIs());
	}
	
	@Override
	public int hashCode() {
		return mSig.hashCode();
	}

	@Override
	public String toString() {
		return mSig.toString();
	}
	
	public boolean isEmpty() {
		return mSig.isEmpty();
	}
	
	public void clear() {
		mSig.clear();
	}
	
	public static boolean containsSubsignature(Collection<Signature> sigs, Signature signature, boolean proper) {
		for (Signature sig : sigs) {
			if (sig.getURIs().containsAll(signature.getURIs()) && (!proper || sig.getURIs().size() > signature.getURIs().size())) {
				return true;
			}
		}
		
		return false;
	}
	
	public static boolean containsSupersignature(Collection<Signature> sigs, Signature signature, boolean proper) {
		for (Signature sig : sigs) {
			if (signature.getURIs().containsAll(sig.getURIs()) && (!proper || signature.getURIs().size() > sig.getURIs().size())) {
				return true;
			}
		}
		
		return false;
	}

	public static Signature intersection(Signature... signatures) {
		Signature intersection = new Signature(signatures[0]);
		
		for (int i = 1; i < signatures.length && !intersection.isEmpty(); i++) {
			intersection.getURIs().retainAll(signatures[i].getURIs());
		}
		
		return intersection;
	}	
	
	public static Signature union(Signature... signatures) {
		Signature union = new Signature();
		
		for (Signature sig : signatures) {
			union.add(sig);
		}
		
		return union;
	}
	
	public static Signature union(Collection<Signature> signatures) {
		Signature union = new Signature();
		
		for (Signature sig : signatures) {
			union.add(sig);
		}
		
		return union;
	}

	@Override
	public Iterator<URI> iterator() {
		return mSig.iterator();
	}
}